/*******************************************************************************
** 文件名称：i2c.c
** 文件作用：I2C
** 编写作者：Tom Free 付瑞彪
** 编写时间：2021-05-30
** 文件备注：
** 更新记录：
**           2021-05-30 -> 创建文件
**                                                            <Tom Free 付瑞彪>
**
**           Copyright (c) 2018-2021 付瑞彪 All Rights Reserved
**
**       1 Tab == 4 Spaces     UTF-8     ANSI C Language(C99)
*******************************************************************************/

#include "i2c.h"
#include "chip_cfg.h"
#include "chip_delay.h"

/* 端口寄存器定义 */
#define I2C_DDR             DDRC    /* 方向寄存器 */
#define I2C_PORTR           PORTC   /* 输出寄存器 */
#define I2C_PINR            PINC    /* 输入寄存器 */

#if !I2C_USE_SOFT
/* 硬件I2C的端口 */
#define I2C_SDA_PIN         0x02    /* PC1 */
#define I2C_SCL_PIN         0x01    /* PC0 */
#endif  /* !I2C_USE_SOFT */

#if I2C_USE_SOFT
/* 画板时把SDA和SCL画反了 */
#define I2C_SDA_PIN         0x01    /* PC0 */
#define I2C_SCL_PIN         0x02    /* PC1 */
#endif  /* I2C_USE_SOFT */

#if !I2C_USE_SOFT
/* 硬件I2C */
/* I2C常用寄存器位定义 */
#define TWPS0               0
#define TWPS1               1
#define TWEN                2
#define TWIE                0
#define TWEA                6
#define TWINT               7
#define TWSTA               5
#define TWSTO               4

/* 状态定义 */
#define TW_START            0x08
#define TW_REP_START        0x10
#define TW_MT_SLA_ACK       0x18
#define TW_MT_SLA_NACK      0x20
#define TW_MT_DATA_ACK      0x28
#define TW_MT_DATA_NACK     0x30
#define TW_MT_ARB_LOST      0x38
#define TW_MR_ARB_LOST      0x38
#define TW_MR_SLA_ACK       0x40
#define TW_MR_SLA_NACK      0x48
#define TW_MR_DATA_ACK      0x50
#define TW_MR_DATA_NACK     0x58

/* I2C初始化 */
void i2c_init(void)
{
    I2C_DDR |= I2C_SDA_PIN | I2C_SCL_PIN;   /* 输出模式 */
    I2C_PORTR |= I2C_SDA_PIN | I2C_SCL_PIN;  /* 使能上拉电阻和输出高电平 */

    TWSR = 0x01;    /* 2 Wire Bus initialization */
    TWBR = 0x01;    /* Generate Acknowledge Pulse:On */
    TWAR = 0x00;    /* 2 Wire Bus Slave Address:0h */
    TWCR = 0x44;    /* General Call Recognition:Off,Bit Rate: 250.000 kHz */
}

/* 开始I2C总线数据传输 */
void i2c_start(void)
{
    TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
    while (!(TWCR & (1 << TWINT)));
}

/* 结束I2C总线数据传输 */
void i2c_stop(void)
{
  	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

/* I2C总线写一个字节数据 */
bool i2c_write_byte(uint8_t data)
{
    bool ack = true;

    TWDR = data;
    TWCR = (1 << TWINT) | (1 << TWEN);

    while (!(TWCR & (1 << TWINT)));

    if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
    {
        ack = false;
    }
    return ack;
}

/* I2C总线读一个字节数据，ack表示是否应答 */
uint8_t i2c_read_byte(bool ack)
{
    if (ack)
    {
        TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
    }
    else
    {
        TWCR = (1 << TWINT) | (1 << TWEN);
    }

    while (!(TWCR & (1 << TWINT)));

    return (TWDR);
}

#else   /* I2C_USE_SOFT */
/* 软件I2C */
#define I2C_Delay()         delay_us(2)
#define I2C_SCL_Reset()     I2C_PORTR &= ~I2C_SCL_PIN
#define I2C_SCL_Set()       I2C_PORTR |= I2C_SCL_PIN
#define I2C_SDA_Reset()     I2C_PORTR &= ~I2C_SDA_PIN
#define I2C_SDA_Set()       I2C_PORTR |= I2C_SDA_PIN
#define I2C_SDA_In_Pullup() I2C_SDA_Set(); I2C_DDR &= ~I2C_SDA_PIN
#define I2C_SDA_Out_High()  I2C_SDA_Set(); I2C_DDR |= I2C_SDA_PIN

/* 初始化 */
void i2c_init(void)
{
    I2C_SDA_Set();
    I2C_SCL_Set();
    I2C_DDR |= I2C_SDA_PIN | I2C_SCL_PIN;
    delay_ms(2);
}

/* 启动传输 */
void i2c_start(void)
{
    I2C_SDA_Set();
    I2C_SCL_Set();
    I2C_Delay();    // 大于4.7us
    I2C_SDA_Reset();
    I2C_Delay();    // 大于4us
}

/* 停止传输 */
void i2c_stop(void)
{
    I2C_SDA_Reset();
    I2C_Delay();
    I2C_SCL_Set();
    I2C_Delay();
    I2C_SDA_Set();
    I2C_Delay();
}

/* 发送位0 */
static void i2c_send_bit_0(void)
{
    I2C_SCL_Reset();
    I2C_Delay();
    I2C_SDA_Reset();
    I2C_Delay();
    I2C_SCL_Set();
    I2C_Delay();    // 大于4us
    I2C_SCL_Reset();
    I2C_Delay();
}

/* 发送位1 */
static void i2c_send_bit_1(void)
{
    I2C_SCL_Reset();
    I2C_Delay();
    I2C_SDA_Set();
    I2C_Delay();
    I2C_SCL_Set();
    I2C_Delay();    //
    I2C_SCL_Reset();
    I2C_Delay();    //
}

/* 等待ack */
static bool i2c_wait_ack(void)
{
    bool temp;
    I2C_SCL_Reset();
    I2C_Delay();
    I2C_SDA_Set();
    I2C_DDR &= ~I2C_SDA_PIN;
    I2C_Delay();
    I2C_SCL_Set();
    I2C_Delay();
    if (I2C_PINR & I2C_SDA_PIN)
    {
        temp = false;
    }
    else
    {
        temp = true;
    }
    I2C_SCL_Reset();
    I2C_Delay();
    I2C_DDR |= I2C_SDA_PIN;
    I2C_Delay();
    return temp;
}

/* 写字节 */
bool i2c_write_byte(uint8_t I2C_data)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        I2C_SCL_Reset();
        I2C_Delay();
        if (I2C_data & 0x80)
        {
            I2C_SDA_Set();
        }
        else
        {
            I2C_SDA_Reset();
        }
        I2C_data <<= 1;
        I2C_SCL_Set();
        I2C_Delay();
    }
    return i2c_wait_ack();//等待应答
}

/* 读字节 */
uint8_t i2c_read_byte(bool ack)
{
    uint8_t i, I2C_data = 0;
    I2C_SDA_Set();
    I2C_DDR &= ~I2C_SDA_PIN;
    for (i = 0; i < 8; i++)
    {
        I2C_Delay();
        I2C_SCL_Set();
        I2C_Delay();
        I2C_data <<= 1;
        if (I2C_PINR & I2C_SDA_PIN)
        {
            I2C_data |= 0x01;
        }
        I2C_SCL_Reset();
    }
    I2C_DDR |= I2C_SDA_PIN;
    if (ack)
    {
        i2c_send_bit_0();
    }
    else
    {
        i2c_send_bit_1();
    }
    return I2C_data;
}

#endif  /* I2C_USE_SOFT */
